﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace LiteFramework
{
    /// <summary>
    /// 数据包。已实现接口: IComparable, IComparer。如需改变比较规则，可重写 int Compare(object x, object y) 方法
    /// <para>　实现接口: IComparable, IComparer</para>
    /// </summary>
    [Serializable]
    [ComVisible(true)]
    public abstract class Bag : IComparable, IComparer
    {
        internal protected readonly HashtableSerializationProxy element = new HashtableSerializationProxy();
        internal protected readonly HashtableSerializationProxy originalElement = new HashtableSerializationProxy();
        internal protected readonly Hashtable propertyVersion = new Hashtable(50);
        /// <summary>
        /// 版本起始值，值为0时，代表属性未被修改。默认0
        /// </summary>
        internal protected int versionStart = 0;

        private Guid _guid = NewComb();
        private sbyte _changed = -1;
        private bool _needVersion = true;

        #region 构造

        public Bag()
        {
        }

        public Bag(Guid guid)
        {
            _guid = guid;
        }

        public Bag(DataRow dataRow)
        {
            this.InitData(dataRow);
        }

        protected Bag(Guid guid, HashtableSerializationProxy hsp)
        {
            _guid = guid;
            element = hsp;
        }

        #endregion

        #region 属性

        [XmlAttribute()]
        public Guid Guid
        {
            get
            {
                return _guid;
            }
            protected set
            {
                _guid = value;
            }
        }

        [XmlIgnore()]
        protected virtual object this[string key]
        {
            get
            {
                return GetValue(key);
            }
            set
            {
                SetValue(key, value);
            }
        }

        /// <summary>
        /// 是否需要版本控制，默认 true
        /// </summary>
        protected bool NeedVersion
        {
            get { return this._needVersion; }
            set { this._needVersion = value; }
        }

        #endregion

        #region Get, Set, Remove, Clear

        protected virtual string[] GetKeys()
        {
            string[] keys = new string[this.element.Count];
            this.element.Keys.CopyTo(keys, 0);

            return keys;
        }

        protected virtual object[] GetValues()
        {
            object[] values = new object[this.element.Count];
            this.element.Values.CopyTo(values, 0);

            return values;
        }

        protected virtual object GetValue(string key)
        {
            return this.GetValueByKey(key, null);
        }

        protected virtual T GetValue<T>(string key, int decimals)
        {
            object o = this.GetValueByKey(key, null);
            if (o is T)
            {
                if (o is decimal)
                    return (T)Convert.ChangeType(Math.Round((decimal)o, decimals, MidpointRounding.AwayFromZero), typeof(decimal));
                else if (o is decimal? && ((decimal?)o).HasValue)
                    return (T)Convert.ChangeType(Math.Round((decimal)o, decimals, MidpointRounding.AwayFromZero), typeof(decimal));

                return (T)o;
            }
            else
                return default(T);
        }
        protected virtual T GetValue<T>(string key)
        {
            object o = this.GetValueByKey(key, null);
            if (o is T)
                return (T)o;
            else
                return default(T);
        }

        protected virtual string GetValue(string key, string defaultValue)
        {
            object o = this.GetValueByKey(key, defaultValue);
            if (o != null)
                return (string)o;
            else
                return defaultValue;
        }

        protected virtual bool GetValue(string key, bool defaultValue)
        {
            return (bool)this.GetValueByKey(key, defaultValue);
        }

        protected virtual long GetValue(string key, long defaultValue)
        {
            return (long)this.GetValueByKey(key, defaultValue);
        }

        protected virtual int GetValue(string key, int defaultValue)
        {
            return (int)this.GetValueByKey(key, defaultValue);
        }

        protected virtual int GetValue(string key, short defaultValue)
        {
            return (short)this.GetValueByKey(key, defaultValue);
        }

        protected virtual decimal GetValue1(string key, int decimals)
        {
            return this.GetValue1(key, decimals, decimal.Zero);
        }
        protected virtual decimal GetValue1(string key, int decimals, decimal defaultValue)
        {
            return Math.Round(this.GetValue(key, defaultValue), decimals, MidpointRounding.AwayFromZero);
        }
        protected virtual decimal GetValue(string key, decimal defaultValue)
        {
            return (decimal)this.GetValueByKey(key, defaultValue);
        }

        protected virtual decimal? GetValue2(string key, int decimals)
        {
            return this.GetValue2(key, decimals, decimal.Zero);
        }
        protected virtual decimal? GetValue2(string key, int decimals, decimal? defaultValue)
        {
            decimal? value = this.GetValue2(key, defaultValue);
            if (value.HasValue)
                return Math.Round(value.Value, decimals, MidpointRounding.AwayFromZero);
            else
                return defaultValue;
        }
        protected virtual decimal? GetValue2(string key, decimal? defaultValue)
        {
            return (decimal?)this.GetValueByKey(key, defaultValue);
        }

        protected virtual float GetValue(string key, float defaultValue)
        {
            return (float)this.GetValueByKey(key, defaultValue);
        }

        protected virtual double GetValue(string key, double defaultValue)
        {
            return (double)this.GetValueByKey(key, defaultValue);
        }
        protected virtual double GetValue(string key, int decimals, double defaultValue)
        {
            return Math.Round(this.GetValue(key, defaultValue), decimals, MidpointRounding.AwayFromZero);
        }

        protected virtual sbyte GetValue(string key, sbyte defaultValue)
        {
            return (sbyte)this.GetValueByKey(key, defaultValue);
        }

        protected virtual DateTime GetValue(string key, DateTime defaultValue)
        {
            return (DateTime)this.GetValueByKey(key, defaultValue);
        }

        protected virtual TimeSpan GetValue(string key, TimeSpan defaultValue)
        {
            return (TimeSpan)this.GetValueByKey(key, defaultValue);
        }

        protected virtual object GetValue(string key, object defaultValue)
        {
            return this.GetValueByKey(key, defaultValue);
        }

        private object GetValueByKey(string key, object defaultValue)
        {
            if (key != null)
            {
                object value = this.element[key];
                if (value == null || value == DBNull.Value)
                {
                    return defaultValue;
                }
                else
                {
                    return value;
                }
            }
            else
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// 属性赋值（触发OnPropertyChanged事件，有别于LoadValue）
        /// </summary>
        /// <param name="key">属性名</param>
        /// <param name="value">属性值</param>
        protected virtual void SetValue(string key, object value)
        {
            this.setValue(key, value, false); // 触发OnPropertyChanged事件
        }

        /// <summary>
        /// 属性赋值（触发OnPropertyChanged事件，有别于LoadValue）
        /// </summary>
        /// <param name="key">属性名</param>
        /// <param name="value">属性值</param>
        /// <param name="decimals">保留小数位</param>
        protected virtual void SetValue(string key, decimal? value, int decimals)
        {
            if (value.HasValue)
                value = Math.Round(value.Value, decimals, MidpointRounding.AwayFromZero);
            this.setValue(key, value, false); // 触发OnPropertyChanged事件
        }
        /// <summary>
        /// 属性赋值（触发OnPropertyChanged事件，有别于LoadValue）
        /// </summary>
        /// <param name="key">属性名</param>
        /// <param name="value">属性值</param>
        /// <param name="decimals">保留小数位</param>
        protected virtual void SetValue(string key, decimal value, int decimals)
        {
            value = Math.Round(value, decimals, MidpointRounding.AwayFromZero);
            this.setValue(key, value, false); // 触发OnPropertyChanged事件
        }

        /// <summary>
        /// 属性赋值（触发OnPropertyChanged事件，有别于LoadValue）
        /// </summary>
        /// <param name="key">属性名</param>
        /// <param name="value">属性值</param>
        /// <param name="mode"></param>
        protected virtual void SetValue(string key, string value, TextHelper.MatchMode mode)
        {
            if (value != null)
            {
                value = TextHelper.Trim(value, mode);
            }

            this.setValue(key, value, false); // 触发OnPropertyChanged事件
        }

        /// <summary>
        /// 加载数据（不触发OnPropertyChanged事件，有别于SetValue）
        /// </summary>
        /// <param name="key">属性名</param>
        /// <param name="value">属性值</param>
        protected virtual void LoadValue(string key, object value)
        {
            this.setValue(key, value, true);
        }

        /// <summary>
        /// 加载数据（不触发OnPropertyChanged事件，有别于SetValue）
        /// </summary>
        /// <param name="key">属性名</param>
        /// <param name="value">属性值</param>
        /// <param name="mode">移除空格的方式</param>
        protected virtual void LoadValue(string key, string value, TextHelper.MatchMode mode)
        {
            if (value != null)
            {
                value = TextHelper.Trim(value, mode);
            }

            this.setValue(key, value, true);
        }

        /// <summary>
        /// 加载数据
        /// </summary>
        /// <param name="key">属性名</param>
        /// <param name="value">属性值</param>
        /// <param name="isLoading">是否正在加载数据。true,正在加载，不触发OnPropertyChanged事件</param>
        private void setValue(string key, object value, bool isLoading)
        {
            if (key != null)
            {
                object oldValue = this.element[key];

                if (!isLoading)
                {
                    CancelEventArgs cancel = new CancelEventArgs(false);

                    this.OnPropertyChanging(key);
                    this.OnPropertyChanging(key, oldValue, ref value, cancel);

                    if (cancel != null && cancel.Cancel) return;
                }

                this.element[key] = value;

                bool isChanged = !((value == oldValue) || (((value != null) && (oldValue != null)) && value.Equals(oldValue)));

                if (!isLoading)
                {
                    if (isChanged)
                    {
                        this.SetChanged();

                        //// 向客户端发出属性值已更改的通知
                        //this.notifyPropertyChanged(key);
                        // 处理定制信息
                        this.OnPropertyChanged(key);
                        this.OnPropertyChanged(key, oldValue, ref value);
                    }
                }

                if (this._needVersion)
                {
                    if (!this.originalElement.ContainsKey(key)) // 原始版本不存在时，开始维护原始版本
                        this.originalElement[key] = (versionStart == 0 ? value : oldValue); // 0代表信息未修改，使用当前版本作为原始版本

                    if (propertyVersion.ContainsKey(key))
                    {
                        if (isChanged)
                        {
                            if (value == this.originalElement[key])
                                propertyVersion[key] = 0;
                            else
                                propertyVersion[key] = (int)propertyVersion[key] + 1;
                        }
                    }
                    else
                    {
                        propertyVersion[key] = versionStart;
                    }
                }
            }
        }

        /// <summary>
        /// 删除属性值
        /// </summary>
        /// <param name="key"></param>
        protected virtual void Remove(string key)
        {
            if (key != null && HasKey(key))
            {
                object old = this.element[key];

                this.element.Remove(key);
                this.SetChanged();

                this.OnPropertyChanged(key);
                //this.OnPropertyChanged(key, old, null);
            }
        }

        /// <summary>
        /// 清空对象
        /// </summary>
        protected virtual void Clear()
        {
            this.element.Clear();
            this.SetChanged();

            this.OnPropertyChanged(null);
            //this.OnPropertyChanged(null, null, null);
        }

        /// <summary>
        /// 设置属性值为null
        /// </summary>
        /// <param name="key"></param>
        protected virtual void SetNull(string key)
        {
            this.SetValue(key, null);
        }

        /// <summary>
        /// 判断属性值是否为空
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        protected virtual bool IsNull(string key)
        {
            if (HasKey(key))
            {
                return (this.element[key] == null || this.element[key] == DBNull.Value);
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// 判断是否存在属性值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        protected virtual bool HasKey(string key)
        {
            return this.element.ContainsKey(key);
        }

        /// <summary>
        /// 属性值改变前调用
        /// </summary>
        /// <param name="propertyName"></param>
        protected virtual void OnPropertyChanging(string propertyName) { }
        /// <summary>
        /// 属性值改变前调用
        /// </summary>
        /// <param name="propertyName"></param>
        /// <param name="oldValue"></param>
        /// <param name="newValue"></param>
        /// <param name="cancel"></param>
        protected virtual void OnPropertyChanging(string propertyName, object oldValue, ref object newValue, CancelEventArgs cancel) { }

        /// <summary>
        /// 属性值改变后调用
        /// </summary>
        /// <param name="propertyName"></param>
        protected virtual void OnPropertyChanged(string propertyName) { }
        /// <summary>
        /// 属性值改变后调用
        /// </summary>
        /// <param name="propertyName"></param>
        /// <param name="oldValue"></param>
        /// <param name="newValue"></param>
        protected virtual void OnPropertyChanged(string propertyName, object oldValue, ref object newValue) { }

        /// <summary>
        /// 重置对象已修改的标识：未修改
        /// </summary>
        public virtual void ResetChanges()
        {
            _changed = 0;
        }

        /// <summary>
        /// 设置对象已修改标识为：已修改
        /// </summary>
        private void SetChanged()
        {
            if (_changed != -1)
                _changed = 1;
        }

        /// <summary>
        /// 判断对象是否已修改
        /// </summary>
        /// <returns></returns>
        public virtual bool IsChanged()
        {
            return (_changed == 1);
        }

        #endregion

        #region Merge

        public void Merge(Bag b)
        {
            Guid guid = _guid;
            b.CopyTo(this);
            _guid = guid;

            this.OnPropertyChanged(null);
            //this.OnPropertyChanged(null, null, null);
        }

        protected void CopyTo(Bag b)
        {
            foreach (DictionaryEntry entry in this.element)
                b.element[entry.Key] = entry.Value;

            b._guid = _guid;
            b._changed = _changed;
        }

        #endregion

        #region InitData
        internal void InitData(DataRow dataRow)
        {
            DataTable dataTable = dataRow.Table;
            DataColumnCollection columns = dataTable.Columns;
            foreach (DataColumn column in columns)
            {
                if (String.Compare(column.ColumnName, "Guid", true) == 0)
                {
                    if (dataRow[column] != DBNull.Value)
                    {
                        if (column.DataType.Equals(typeof(Guid)))
                        {
                            _guid = (Guid)dataRow[column];
                        }
                        else if (column.DataType.Equals(typeof(string)))
                        {
                            string s = (string)dataRow[column];
                            if (!String.IsNullOrEmpty(s))
                                _guid = new Guid(s);
                            else
                                _guid = Guid.Empty;
                        }
                    }
                    else
                    {
                        _guid = Guid.Empty;
                    }
                }
                else
                {
                    //this.SetValue(column.ColumnName, dataRow[column]);
                    this.element[column.ColumnName] = dataRow[column];
                }
            }
        }
        #endregion

        #region Educe
        public bool Educe(DataRow dataRow)
        {
            return this.Educe(dataRow, false);
        }

        public bool Educe(DataRow dataRow, bool addColumn)
        {
            bool notAction = true;
            DataTable dataTable = dataRow.Table;

            foreach (DataColumn column in dataTable.Columns)
            {
                if (String.Compare(column.ColumnName, "Guid", true) == 0)
                {
                    if (column.DataType.Equals(typeof(Guid)))
                    {
                        dataRow[column] = _guid;
                        notAction = false;
                    }
                    else if (column.DataType.Equals(typeof(string)))
                    {
                        dataRow[column] = _guid.ToString();
                        notAction = false;
                    }
                    break;
                }
            }

            string[] keys = this.GetKeys();

            foreach (string key in keys)
            {
                if (addColumn && !dataTable.Columns.Contains(key))
                {
                    object obj = this[key];
                    if (obj != null && !(obj is IList))
                    {
                        Type t = obj.GetType();
                        if (t.IsGenericType)
                            t = Nullable.GetUnderlyingType(t);

                        if (t.Equals(typeof(bool)) ||
                            t.Equals(typeof(byte)) ||
                            t.Equals(typeof(char)) ||
                            t.Equals(typeof(DateTime)) ||
                            t.Equals(typeof(decimal)) ||
                            t.Equals(typeof(double)) ||
                            t.Equals(typeof(int)) ||
                            t.Equals(typeof(long)) ||
                            t.Equals(typeof(sbyte)) ||
                            t.Equals(typeof(float)) ||
                            t.Equals(typeof(string)) ||
                            t.Equals(typeof(TimeSpan)) ||
                            t.Equals(typeof(uint)) ||
                            t.Equals(typeof(ulong)))
                        {
                            DataColumn column = dataTable.Columns.Add(key, t);
                            column.Caption = key.ToUpper();
                        }
                    }
                }

                if (dataTable.Columns.Contains(key))
                {
                    DataColumn column = dataTable.Columns[key];
                    if (String.IsNullOrEmpty(column.Caption))
                        column.Caption = key.ToUpper();

                    object value = this.GetValue(key);

                    //if (value != null && column.DataType.Equals(value.GetType()))
                    //{
                    //    dataRow[column] = value;
                    //    notAction = false;
                    //}
                    //else if (value != null && value is IConvertible)
                    //{
                    //    dataRow[column] = Convert.ChangeType(value, column.DataType);
                    //    notAction = false;
                    //}
                    if (value != null)
                    {
                        dataRow[column] = value;
                        notAction = false;
                    }
                    else if (column.AllowDBNull)
                    {
                        dataRow[column] = DBNull.Value;
                    }
                }
            }

            return !notAction;
        }
        #endregion

        #region Serialize

        public virtual void Serialize(string fileName)
        {
            FileStream stream = new FileStream(fileName, FileMode.Create);
            using (stream)
            {
                try
                {
                    Serialize(stream);
                }
                finally
                {
                    stream.Close();
                }
            }
        }

        public virtual void Serialize(Stream stream)
        {
            SoapFormatter formatter = new SoapFormatter();
            Serialize(stream, formatter);
        }

        public virtual void Serialize(string fileName, IFormatter formatter)
        {
            FileStream stream = new FileStream(fileName, FileMode.Create);
            using (stream)
            {
                try
                {
                    Serialize(stream, formatter);
                }
                finally
                {
                    stream.Close();
                }
            }
        }

        public virtual void Serialize(Stream stream, IFormatter formatter)
        {
            formatter.Serialize(stream, this);
        }

        public static Bag Deserialize(Stream stream, IFormatter formatter)
        {
            return Deserialize<Bag>(stream, formatter);
        }

        protected static T Deserialize<T>(string fileName) where T : class
        {
            FileStream stream = new FileStream(fileName, FileMode.Open);
            using (stream)
            {
                try
                {
                    return (T)Deserialize<T>(stream);
                }
                finally
                {
                    stream.Close();
                }
            }
        }

        protected static T Deserialize<T>(Stream stream) where T : class
        {
            SoapFormatter formatter = new SoapFormatter();
            return (T)Deserialize<T>(stream, formatter);
        }

        protected static T Deserialize<T>(string fileName, IFormatter formatter) where T : class
        {
            FileStream stream = new FileStream(fileName, FileMode.Open);
            using (stream)
            {
                try
                {
                    return (T)Deserialize<T>(stream, formatter);
                }
                finally
                {
                    stream.Close();
                }
            }
        }

        protected static T Deserialize<T>(Stream stream, IFormatter formatter) where T : class
        {
            return (T)formatter.Deserialize(stream);
        }

        #endregion

        #region Xml

        public virtual void WriteXml(Stream stream)
        {
            XmlSerializer xs = new XmlSerializer(this.GetType());
            xs.Serialize(stream, this);
        }

        public virtual void WriteXml(System.Xml.XmlWriter writer)
        {
            XmlSerializer xs = new XmlSerializer(this.GetType());
            xs.Serialize(writer, this);
        }

        public virtual void WriteXml(string fileName)
        {
            using (FileStream fs = new FileStream(fileName, FileMode.Create))
            {
                WriteXml(fs);
                fs.Close();
            }
        }

        protected static T ReadXml<T>(Stream stream) where T : class
        {
            XmlSerializer xs = new XmlSerializer(typeof(T));
            return (T)xs.Deserialize(stream);
        }

        protected static T ReadXml<T>(XmlReader reader) where T : class
        {
            XmlSerializer xs = new XmlSerializer(typeof(T));
            return (T)xs.Deserialize(reader);
        }

        protected static T ReadXml<T>(string fileName) where T : class
        {
            T obj = null;

            using (FileStream fs = new FileStream(fileName, FileMode.Open))
            {
                obj = ReadXml<T>(fs);
                fs.Close();
            }

            return obj;
        }
        #endregion

        #region ToTable

        internal static DataTable ToTable<T>(IList<T> list, bool complex) where T : Bag
        {
            Type type = typeof(T);
            if (IsSubclassOfEntity(type))
            {
                return Entity<T>.ToTable(list, complex);
            }
            else
            {
                DataTable table = new DataTable(type.Name);

                DataColumn column = table.Columns.Add("Guid", typeof(string));
                //column.Caption = "全局标识";
                column.Caption = "";

                table.PrimaryKey = new DataColumn[] { column };

                if (list != null)
                {
                    foreach (Bag b in list)
                    {
                        if (b != null)
                        {
                            DataRow dataRow = table.NewRow();
                            if (b.Educe(dataRow, true))
                                table.Rows.Add(dataRow);
                        }
                    }
                }

                table.AcceptChanges();
                return table;
            }
        }

        #endregion

        #region IndexOf

        protected static int IndexOf(Bag[] array, Bag value)
        {
            if (array != null && array.Length != 0)
            {
                for (int index = 0; index < array.Length; index++)
                {
                    if (array[index] == value)
                        return index;
                }
            }

            return -1;
        }

        #endregion

        #region IComparable 成员

        /// <summary>
        /// IComparable 成员
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        int IComparable.CompareTo(object obj)
        {
            return this.Compare(this, obj);
        }

        #endregion

        #region IComparer 成员

        /// <summary>
        /// IComparer 成员
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public virtual int Compare(object x, object y)
        {
            if (object.ReferenceEquals(x, y)) return 0;
            if (y == null) return 1;
            if (x == null) return -1;

            Bag ex = x as Bag;
            if (ex == null)
                throw new ArgumentException("Not a " + this.GetType().Name + " object", "x");

            Bag ey = y as Bag;
            if (ey == null)
                throw new ArgumentException("Not a " + this.GetType().Name + " object", "y");

            return ex.Guid.CompareTo(ey.Guid);
        }

        #endregion

        #region ToString
        public override string ToString()
        {
            return Guid.ToString();
        }
        #endregion

        #region Comb

        private static Guid NewComb()
        {
            DateTime now = DateTime.Now;
            TimeSpan days = new TimeSpan(now.Ticks - DateTime.MinValue.Ticks);
            TimeSpan msecs = new TimeSpan(now.Ticks - now.Date.Ticks);

            StringBuilder sb = new StringBuilder();

            string s = days.Days.ToString("0000000000");
            sb.Append(s.Substring(s.Length - 7));

            s = msecs.TotalMilliseconds.ToString("0.0000");

            int pos = s.IndexOf('.');
            if (pos == -1)
                pos = 0;

            s = s.Replace(".", String.Empty).PadLeft(10, '0');
            sb.Append(s);

            s = sb.ToString();
            int a = System.Convert.ToInt32(s.Substring(0, 9));
            short b = System.Convert.ToInt16(s.Substring(9, 4));
            short c = System.Convert.ToInt16(s.Substring(13, 4));

            byte[] d = new byte[8];

            byte[] bts = System.Guid.NewGuid().ToByteArray();
            if (Environment.OSVersion.Platform == PlatformID.Win32Windows)
                Array.Reverse(bts); // Win9x 的 GUID 后段全部相同，因此反转取前段

            Array.Copy(bts, bts.Length - 8, d, 0, 8);

            d[0] = (byte)pos;

            return new Guid(a, b, c, d);
        }

        public DateTime? ParseGuid()
        {
            if (_guid == null)
                return null;

            string s = _guid.ToString();
            if (!s.StartsWith("045e", StringComparison.OrdinalIgnoreCase))
                return null;

            try
            {
                byte[] bytes = _guid.ToByteArray();

                byte[] ba = new byte[] { bytes[0], bytes[1], bytes[2], bytes[3] };
                byte[] bb = new byte[] { bytes[4], bytes[5] };
                byte[] bc = new byte[] { bytes[6], bytes[7] };

                int a = BitConverter.ToInt32(ba, 0);
                int b = BitConverter.ToInt16(bb, 0);
                int c = BitConverter.ToInt16(bc, 0);

                byte decPos = bytes[8];

                string rs = ("0" + a.ToString() + b.ToString() + c.ToString()).PadRight(17, '0');
                int days = int.Parse(rs.Substring(0, 7));

                string ms = rs.Substring(7);
                if (decPos != 0 && decPos < ms.Length)
                    ms = ms.Insert(decPos, ".");

                double msecs = double.Parse(ms);

                DateTime date = new DateTime();
                date = date.AddDays(days);
                date = date.AddMilliseconds(msecs);

                return date;
            }
            catch
            {
                return null;
            }
        }

        #endregion

        #region static Method

        /// <summary>
        /// 判断type是否继承自 Hykon.BaseFramework.Entity
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        internal static bool IsSubclassOfEntity(Type type)
        {
            while (type.BaseType != null)
            {
                type = type.BaseType;
                if (type.FullName.StartsWith("Hykon.BaseFramework.Entity`1"))
                    return true;
            }

            return false;
        }

        /// <summary>
        /// 搜索属性的标签
        /// </summary>
        /// <typeparam name="T">指定从此类中搜索</typeparam>
        /// <typeparam name="A">要搜索的标签类型</typeparam>
        /// <param name="propertyName">属性名</param>
        /// <param name="inherit">指定是否搜索该成员的继承链以查找这些属性</param>
        /// <returns></returns>
        public static A[] GetPropertyAttribute<T, A>(string propertyName, bool inherit)
            where T : class
            where A : Attribute
        {
            if (!string.IsNullOrEmpty(propertyName))
            {
                PropertyInfo info = typeof(T).GetProperty(propertyName);
                return info.GetCustomAttributes(typeof(A), inherit) as A[];
            }

            return null;
        }

        /// <summary>
        /// 搜索字段的标签
        /// </summary>
        /// <typeparam name="T">指定从此类中搜索</typeparam>
        /// <typeparam name="A">要搜索的标签类型</typeparam>
        /// <param name="fieldName">字段名</param>
        /// <param name="inherit">指定是否搜索该字段的继承链以查找这些属性</param>
        /// <returns></returns>
        public static A[] GetFieldAttribute<T, A>(string fieldName, bool inherit)
            where T : class
            where A : Attribute
        {
            if (!string.IsNullOrEmpty(fieldName))
            {
                FieldInfo info = typeof(T).GetField(fieldName);
                return info.GetCustomAttributes(typeof(A), inherit) as A[];
            }

            return null;
        }

        #endregion

        #region notifyPropertyChanged
        /// <summary>
        /// 向客户端发出属性值已更改的通知
        /// </summary>
        /// <param name="propertyName">属性名称</param>
        protected virtual void notifyPropertyChanged(string propertyName)
        {

        }
        #endregion
    }
}